package Controllers;

import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.TimeUnit;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import common.Settings;
import common.TimerUpdater;
import entities.Building;
import entities.Campus;
import entities.Class;
import entities.ClassesAids;
import entities.Course;
import entities.Faculty;
import entities.Lecturer;
import entities.StudyAids;
import Algorithm.Database;
import Algorithm.GeneticAlgorithmRun;
import Algorithm.Individual;
import Client.ChatClient;
import GUI.*;
import MsgPackage.*;
import MsgPackage.GetAllLecturersPack.getInformation;

public class ManagerController
{
	final public static int EXIT = 11;
	final public static int MAIN = 2;
	final public static int AUTO = 3;
	final public static int MAMUAL = 4;
	final public static int LECTURERPREFER = 5;
	final public static int COURSSETTING = 6;
	final public static int EDITCOURESES = 7;
	final public static int EDITCLASS = 8;
	final public static int EDITLECTURER = 9;
	final public static int SETTING = 10;
	final public static int MAGI = 0;
	final public static int NOT_MAGI = 1;

	final public static int EDITCLASSGUI = 20;
	final public static int EDITCOURSGUI = 21;

	private Lecturer_Preferences LP;
	private Automatic_Sheduling AS;
	private Course_Settings CS;
	private Edit_Class ECLSS;
	private Edit_Course ECRS;
	private Edit_Lecturer EL;
	public Manual_Sheduling MS;
	public static int fix = 0;
	public Edit_Course ed;
	private Main_Menu main;
	public Main_Frame manegerMainFrm;
	public LecturerController lecturer_Ctrl;

	private ChatClient client;
	private GetAllLecturersPack LecMsg;
	private GetAllClassesPack ClassMsg;
	private GetAllCoursePack CourseMsg;
	private GetAllFacultyPack FacultyMsg;
	private GetAllCoursesForSchedualingPack ForSchedualingCourseMsg;
	private TimerUpdater timer;
	private Date starttime;

	GeneticAlgorithmRun startalgo;

	public static Database collageDB;

	public ManagerController(Main_Frame mainFrm, ChatClient client)
	{
		this.client = client;
		manegerMainFrm = mainFrm;
		main = new Main_Menu(NOT_MAGI, this);
		manegerMainFrm.add(main.PNL_Main);
	}

	public void BacktoMainMenu(JPanel Panel2Close)
	{
		manegerMainFrm.remove(Panel2Close);
		manegerMainFrm.add(main.PNL_Main);
		manegerMainFrm.repaint();
	}

	public void Load_Lecturer_Preferences(JPanel Panel2Close)
	{
		manegerMainFrm.remove(Panel2Close);
		LP = new Lecturer_Preferences(null, this);
		LP.setLecturers(getAvailableLecturers(getInformation.schedual, false));
		manegerMainFrm.add(LP.PNL_Main);
		// lecturer_Ctrl = new LecturerController(this);
		manegerMainFrm.repaint();
	}

	public void Load_Automatic_Sheduling(JPanel Panel2Close, Database allData, Individual firstIndividual)
	{

		manegerMainFrm.remove(Panel2Close);
		AS = new Automatic_Sheduling(this);
		System.out.println("got me");
		AS.setData(allData);
		manegerMainFrm.add(AS.PNL_Main);
		startalgo = new GeneticAlgorithmRun(firstIndividual, Settings.populationSize, this);
		AS.addActions();
		startTimer();
		startAutoSchedualing();

		manegerMainFrm.repaint();

	}

	// //////////////
	public void Load_Edit_Course(JPanel Panel2Close)
	{
		fix = 0;
		manegerMainFrm.remove(Panel2Close);
		ECRS = new Edit_Course(this);
		ECRS.setCourses(getCourse());
		ECRS.setFaculty(getFaculty());
		ECRS.setAvailableLecturers(getAvailableLecturers(getInformation.nothing, false));
		ECRS.setStudyAids(GetClassAids());
		ECRS.setdefault();

		ECRS.addActions();
		manegerMainFrm.add(ECRS.PNL_Main);
		manegerMainFrm.repaint();
	}

	public void Load_Course_Settings(JPanel Panel2Close)
	{

		manegerMainFrm.remove(Panel2Close);
		// /load all we need

		CS = new Course_Settings(this);
		CS.setFaculty(getFaculty());

		CS.setCourse(getCourse());
		manegerMainFrm.add(CS.PNL_Main);
		manegerMainFrm.repaint();
		CS.addActions();
	}

	public void Load_Edit_Lecturer(JPanel Panel2Close)
	{

		manegerMainFrm.remove(Panel2Close);
		EL = new Edit_Lecturer(this);
		EL.setLec(getAvailableLecturers(getInformation.courses, false));
		EL.setcourse(getCourse());
		manegerMainFrm.add(EL.PNL_Main);
		manegerMainFrm.repaint();
		EL.addActions();
	}

	public void Load_Edit_Class(JPanel Panel2Close)
	{
		manegerMainFrm.remove(Panel2Close);
		ECLSS = new Edit_Class(this);

		ECLSS.setClasses(GetClasses(true));

		ECLSS.setClassStudyAids(GetClassAids());
		ECLSS.setCampus(getCampuses());
		ECLSS.setBuilding(getBuildings());
		// ECLSS.setAidsForExistingClasses(GetAidsForExistingClasses());
		manegerMainFrm.add(ECLSS.PNL_Main);
		ECLSS.addActions();
		manegerMainFrm.repaint();
	}

	public void Load_Manual_Sheduling(JPanel Panel2Close)
	{

		manegerMainFrm.remove(Panel2Close);
		MS = new Manual_Sheduling(this);
		MS.setFaculty(getFaculty());
		MS.setClasses(GetClasses(false));
		MS.setMapCourse(getCourseForSchedualing());
		MS.setLec(getAvailableLecturers(getInformation.all, true));
		MS.setfirstIndividual();
		manegerMainFrm.add(MS.PNL_Main);

		manegerMainFrm.repaint();
		MS.addActions();
	}

	private ArrayList<Lecturer> getAvailableLecturers(getInformation additionalInfo, boolean getOnlyAvialable)
	{
		GetAllLecturersPack AvailableLecturers = new GetAllLecturersPack();
		AvailableLecturers.setAdditionalInfo(additionalInfo);
		if (getOnlyAvialable)
			AvailableLecturers.setGetOnlyAvialable();
		client.handleMessageFromClientUI(AvailableLecturers);
		AvailableLecturers = (GetAllLecturersPack) client.getMessage();

		return (AvailableLecturers.getAllLecturers());

	}

	private ArrayList<Faculty> getFaculty()
	{

		FacultyMsg = new GetAllFacultyPack();
		client.handleMessageFromClientUI(FacultyMsg);
		FacultyMsg = (GetAllFacultyPack) client.getMessage();
		return (FacultyMsg.getAllFaculty());
	}

	private ArrayList<Course> getCourseForSchedualing()
	{

		ForSchedualingCourseMsg = new GetAllCoursesForSchedualingPack();
		ForSchedualingCourseMsg.setAdditionalInfo();
		client.handleMessageFromClientUI(ForSchedualingCourseMsg);
		ForSchedualingCourseMsg = (GetAllCoursesForSchedualingPack) client.getMessage();
		return (ForSchedualingCourseMsg.getAllclass());
	}

	private ArrayList<Course> getCourse()
	{

		CourseMsg = new GetAllCoursePack();
		CourseMsg.setAdditionalInfo();
		client.handleMessageFromClientUI(CourseMsg);
		CourseMsg = (GetAllCoursePack) client.getMessage();
		return (CourseMsg.getAllclass());
	}

	private ArrayList<ClassesAids> GetAidsForExistingClasses()
	{
		GetClassAidsPack ClassAidsMessage = new GetClassAidsPack();
		client.handleMessageFromClientUI(ClassAidsMessage);
		ClassAidsMessage = (GetClassAidsPack) client.getMessage();

		return (ClassAidsMessage.getAllclassAids());
	}

	// ////
	private ArrayList<StudyAids> GetClassAids()
	{
		GetStudyAidsPack studyAidsMessage = new GetStudyAidsPack();
		client.handleMessageFromClientUI(studyAidsMessage);
		studyAidsMessage = (GetStudyAidsPack) client.getMessage();
		return (studyAidsMessage.getAllStudyAids());
	}

	public ArrayList<Class> GetClasses(boolean getAllClasses)
	{
		ClassMsg = new GetAllClassesPack();
		if (!getAllClasses)
			ClassMsg.setOnlyAvailable();
		client.handleMessageFromClientUI(ClassMsg);
		ClassMsg = (GetAllClassesPack) client.getMessage();
		return (ClassMsg.getAllclass());
	}

	private ArrayList<Campus> getCampuses()
	{
		GetCampusPack CampusMsg = new GetCampusPack();
		client.handleMessageFromClientUI(CampusMsg);
		CampusMsg = (GetCampusPack) client.getMessage();
		return (CampusMsg.getAllCampuses());
	}

	private ArrayList<Building> getBuildings()
	{
		GetBuildingsPack BuildingMsg = new GetBuildingsPack();
		client.handleMessageFromClientUI(BuildingMsg);
		BuildingMsg = (GetBuildingsPack) client.getMessage();
		return (BuildingMsg.getAllBuildings());
	}

	public Course CreateNewCourse(Course newCourse)
	{

		NewCoursePack NewCourseMsg = new NewCoursePack();
		NewCourseMsg.setNewCourse(newCourse);
		client.handleMessageFromClientUI(NewCourseMsg);
		NewCourseMsg = (NewCoursePack) client.getMessage();

		return NewCourseMsg.getNewCourse();
	}

	public Course UpdateNewCourse(Course newCourse)
	{

		UpdateCoursePack updateCourseMsg = new UpdateCoursePack();
		updateCourseMsg.setNewCourse(newCourse);
		client.handleMessageFromClientUI(updateCourseMsg);
		updateCourseMsg = (UpdateCoursePack) client.getMessage();

		return updateCourseMsg.getNewCourse();
	}

	public void logout()
	{
		manegerMainFrm.handleLogoutGUI();

	}

	public boolean saveCoureSet(Map<Integer, ArrayList<Course>> coursePerFuculty)
	{
		UpdateEstimatedStudentsNumPerClassPack updateMsg = new UpdateEstimatedStudentsNumPerClassPack();
		updateMsg.setCoursePerFucultyMap(coursePerFuculty);
		client.handleMessageFromClientUI(updateMsg);

		updateMsg = (UpdateEstimatedStudentsNumPerClassPack) client.getMessage();

		return (updateMsg.isSucceed());

	}

	public Lecturer CreateNewLecturer(Lecturer newLecturer)
	{
		NewLecturerPack NewLecturerMsg = new NewLecturerPack();
		NewLecturerMsg.setNewLecturer(newLecturer);
		client.handleMessageFromClientUI(NewLecturerMsg);
		NewLecturerMsg = (NewLecturerPack) client.getMessage();

		return NewLecturerMsg.getNewLecturer();
	}

	public Lecturer UpdateNewLecturer(Lecturer newLecturer)
	{
		UpdateLecturerPack NewLecturerMsg = new UpdateLecturerPack();
		NewLecturerMsg.setNewLecturer(newLecturer);
		client.handleMessageFromClientUI(NewLecturerMsg);
		NewLecturerMsg = (UpdateLecturerPack) client.getMessage();

		return NewLecturerMsg.getNewLecturer();
	}

	public Class CreateNewClass(Class newClass)
	{
		NewClassPack newClassMsg = new NewClassPack();
		newClassMsg.setNewClass(newClass);
		client.handleMessageFromClientUI(newClassMsg);
		newClassMsg = (NewClassPack) client.getMessage();

		return newClassMsg.getNewClass();
	}

	public Class UpdateNewClass(Class newClass)
	{
		UpdateClassPack newClassMsg = new UpdateClassPack();
		newClassMsg.setNewClass(newClass);
		client.handleMessageFromClientUI(newClassMsg);
		newClassMsg = (UpdateClassPack) client.getMessage();

		return newClassMsg.getNewClass();
	}

	public boolean UpdateTable(ArrayList<Lecturer> arrayLecturer)
	{

		UpdateLecturersPreferencesPack NewLecturerscScheduleMsg = new UpdateLecturersPreferencesPack();
		NewLecturerscScheduleMsg.setAllLecturers(arrayLecturer);
		client.handleMessageFromClientUI(NewLecturerscScheduleMsg);
		NewLecturerscScheduleMsg = (UpdateLecturersPreferencesPack) client.getMessage();

		return NewLecturerscScheduleMsg.isSucceed();

	}

	public void setDataBase(Database allData)
	{
		collageDB = allData;
	}

	public void stopAutoSchedualing()
	{
		startalgo.stopRunning();
		try
		{
			startalgo.join();
		} catch (InterruptedException e)
		{
			System.out.println("can't join!!");
		}
		stopTimer();

	}

	public void startAutoSchedualing()
	{
		startalgo.start();

	}

	public void updateProgressBar(double fitness)
	{
		AS.updateProgressBar(fitness);
	}

	public void updatePopCounter(int counter)
	{
		AS.updatePopCounter(counter);
	}

	public void startTimer()
	{
		starttime = new Date();
		timer = new TimerUpdater(this);
		timer.startTimer();

	}

	public void stopTimer()
	{

		timer.StopTimer();

	}

	public void updateRunTimeDisplay()
	{
		long runtime;
		Date date = new Date();
		runtime = date.getTime() - starttime.getTime();

		TimeUnit.MILLISECONDS.toDays(runtime);
		AS.updaterunTime(String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(runtime),
				TimeUnit.MILLISECONDS.toMinutes(runtime) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(runtime)),
				TimeUnit.MILLISECONDS.toSeconds(runtime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(runtime))));
	}
}
